module booth_mult_12bit (
    input  wire [11:0] operand_a,  // 12-bit multiplier
    input  wire [11:0] operand_b,  // 12-bit multiplicand
    output wire [23:0] product     // 24-bit product (output)
);

    wire [174:0] csa_tree_in;
    wire [ 24:0] sum;
    wire [ 24:0] carry;

    pp_generation u_pp_generation (
        .Mant_a_DI(operand_a),   // 输入：被乘数（12位）
        .Mant_b_DI(operand_b),   // 输入：乘数（12位）
        .Pp_DO    (csa_tree_in)  // 输出：PP生成器输出（175位） 
    );

    // CSA树实例化
    acc_csa_tree #(
        .num_inputs (7),  // 输入数量
        .input_width(25)  // 输入位宽
    ) u_acc_csa_tree (
        .INPUT(csa_tree_in),  // 输入
        .OUT0 (sum),          // 输出0
        .OUT1 (carry)         // 输出1
    );

    assign product = sum[23:0] + carry[23:0];

endmodule

// 模块名：pp_generation，用于实现12位乘法器中的部分积生成电路
module pp_generation (
    input  wire [ 11:0] Mant_a_DI,  // 输入：被乘数（12位）
    input  wire [ 11:0] Mant_b_DI,  // 输入：乘数（12位）
    output wire [174:0] Pp_DO       // 7个25位部分积打包输出 (7*25=175位)
);

    wire [24:0] Pp_0_DO;  // 部分积0
    wire [24:0] Pp_1_DO;  // 部分积1
    wire [24:0] Pp_2_DO;  // 部分积2
    wire [24:0] Pp_3_DO;  // 部分积3
    wire [24:0] Pp_4_DO;  // 部分积4
    wire [24:0] Pp_5_DO;  // 部分积5
    wire [24:0] Pp_6_DO;  // 部分积6

    // 扩展乘数，前后各加两个零位，用于Booth编码
    wire [15:0] Mant_b_extended;
    assign Mant_b_extended = {2'b00, Mant_b_DI, 2'b00};

    // Booth编码选择信号
    wire [6:0] Sel_1x_S;  // 选择1x的信号
    wire [6:0] Sel_2x_S;  // 选择2x的信号
    wire [6:0] Sel_sign_S;  // 选择符号的信号

    // 生成7个Booth编码器
    genvar i;
    generate
        for (i = 1; i <= 7; i = i + 1) begin : booth_encoders
            booth_encoder booth_enc (
                .Booth_b_DI (Mant_b_extended[(2*i)+1:(2*i)-1]),  // 每次取3位进行编码
                .Sel_1x_SO  (Sel_1x_S[i-1]),                     // 输出：选择1x
                .Sel_2x_SO  (Sel_2x_S[i-1]),                     // 输出：选择2x
                .Sel_sign_SO(Sel_sign_S[i-1])                    // 输出：选择符号
            );
        end
    endgenerate

    // 扩展被乘数，末尾加0
    wire [13:0] Mant_a_extended;
    assign Mant_a_extended = {1'b0, Mant_a_DI, 1'b0};

    // 7组部分积，每组13位
    wire [12:0] Booth_pp[6:0];

    // 生成7组部分积选择器
    genvar l, j;
    generate
        for (l = 1; l <= 7; l = l + 1) begin : booth_selectors_group
            for (j = 1; j <= 13; j = j + 1) begin : booth_selectors
                booth_selector booth_sel (
                    .Booth_a_DI(Mant_a_extended[j:j-1]),
                    .Sel_1x_SI(Sel_1x_S[l-1]),  // 1x选择信号
                    .Sel_2x_SI(Sel_2x_S[l-1]),  // 2x选择信号
                    .Sel_sign_SI(Sel_sign_S[l-1]),  // 符号选择信号
                    .Booth_pp_DO(Booth_pp[l-1][j-1])  // 输出：根据选择信号生成的部分积位
                );
            end
        end
    endgenerate

    // 组装7个部分积，包括符号扩展和移位
    // 第1个部分积 (位置0)
    assign Pp_0_DO = {9'b000000000, ~Sel_sign_S[0], Sel_sign_S[0], Sel_sign_S[0], Booth_pp[0]};

    // 第2个部分积 (左移2位)
    assign Pp_1_DO = {9'b000000001, ~Sel_sign_S[1], Booth_pp[1], 1'b0, Sel_sign_S[0]};

    // 第3个部分积 (左移4位)
    assign Pp_2_DO = {7'b0000001, ~Sel_sign_S[2], Booth_pp[2], 1'b0, Sel_sign_S[1], 2'b00};

    // 第4个部分积 (左移6位)
    assign Pp_3_DO = {5'b00001, ~Sel_sign_S[3], Booth_pp[3], 1'b0, Sel_sign_S[2], 4'h0};

    // 第5个部分积 (左移8位)
    assign Pp_4_DO = {3'b001, ~Sel_sign_S[4], Booth_pp[4], 1'b0, Sel_sign_S[3], 6'h00};

    // 第6个部分积 (左移10位)
    assign Pp_5_DO = {1'b1, ~Sel_sign_S[5], Booth_pp[5], 1'b0, Sel_sign_S[4], 8'h00};

    // 第7个部分积 (左移12位)
    assign Pp_6_DO = {Booth_pp[6], 1'b0, Sel_sign_S[5], 10'h000};

    assign Pp_DO   = {Pp_6_DO, Pp_5_DO, Pp_4_DO, Pp_3_DO, Pp_2_DO, Pp_1_DO, Pp_0_DO};

endmodule

module booth_encoder (
    Booth_b_DI,
    Sel_1x_SO,
    Sel_2x_SO,
    Sel_sign_SO
);
    input wire [2:0] Booth_b_DI;
    output wire Sel_1x_SO;
    output wire Sel_2x_SO;
    output wire Sel_sign_SO;
    wire Sel_xnor_S;
    assign Sel_1x_SO   = ^Booth_b_DI[1:0];
    assign Sel_xnor_S  = ~(^Booth_b_DI[2:1]);
    assign Sel_2x_SO   = ~(Sel_1x_SO | Sel_xnor_S);
    assign Sel_sign_SO = Booth_b_DI[2];
endmodule

// Booth选择器模块声明，用于Booth乘法算法中的部分积生成
module booth_selector (
    Booth_a_DI,  // 输入信号：被乘数部分位
    Sel_1x_SI,  // 输入信号：选择1倍被乘数的控制信号
    Sel_2x_SI,  // 输入信号：选择2倍被乘数的控制信号
    Sel_sign_SI,  // 输入信号：控制结果符号的信号
    Booth_pp_DO  // 输出信号：生成的部分积位
);
    // 端口定义部分
    input wire [1:0] Booth_a_DI;  // 2位宽的被乘数输入，wire类型
    input wire Sel_1x_SI;  // 1倍被乘数选择控制信号，wire类型
    input wire Sel_2x_SI;  // 2倍被乘数选择控制信号，wire类型
    input wire Sel_sign_SI;  // 符号控制信号，用于确定部分积的符号，wire类型
    output wire Booth_pp_DO;  // 输出的部分积位，wire类型

    // 计算部分积的逻辑表达式
    // 1. (Sel_1x_SI && Booth_a_DI[1])：当选择1倍且被乘数对应位为1时输出1
    // 2. (Sel_2x_SI && Booth_a_DI[0])：当选择2倍且被乘数低位为1时输出1
    // 3. 两种情况取或，再取反得到中间结果
    // 4. 与符号控制信号异或，决定最终符号
    // 5. 最外层再取反，得到最终的部分积位
    assign Booth_pp_DO = ~(~((Sel_1x_SI && Booth_a_DI[1]) | (Sel_2x_SI && Booth_a_DI[0])) ^ Sel_sign_SI);
endmodule
